// 封装skill 相关数据
library SkillVo initializer init requires SkillButtonVo

    // ============================== 扩展说明 ==============================
    // 增加指定大技能的小技能犯法：
    // 1.在初始化中添加小技能id及其关联，并且设置小技能个数
    // 2.在对应的技能函数中实现其功能
    // 3.在随机技能中选中时候设置其对应参数

    // 增加爱大技能方法：
    // 1.编写对应的技能函数
    // 2.在当前技能池中初始化增加其id,并且设置其数组长度
    // 3.添加小技能其小技能如上方法
    // ============================== 扩展说明 ==============================


    globals
        // 技能ID从1开始
        // 当前技能池子中所有技能的id
        integer array allSkillId
        // 当前技能池子中所有技能的id数量
        integer allSkillIdCount = 5


        // 当前玩家已经解锁的技能id
        // 每个玩家预留20个技能id
        // [uid * 20 + id]
        integer array unlockedSkillId
        // 当前玩家已经解锁的技能id数量
        integer array unlockedSkillIdCount
        // 当前玩家已经解锁的技能格子（默认4）
        integer array unlockedSkillGrid


        // 当前卡牌随的技能id(大技能ID)
        // [uid * 8 + cardId]  目前只有三个，后面的预留三个cardId = 0,1,2
        integer array cardSkillId
        // 小技能ID
        integer array cardSkillIdSmall

        // 目前这种设计数据 最多100个小技能（1-100）
        // 父key 表示大技能Id
        // 子key 1-10存储一些基础信息，备用，暂时没用
        // 子key 1 存储当前大技能的小技能最大ID也就是数量
        // 子key 11 存储小技能图标 - 10 就是小技能id
        // 子key 小技能id+100 存储小技能名称
        // 子key 小技能id+200 存储小技能描述
        // 子key 小技能id+300 存储小技能能解锁的最大数量
        // 子key 小技能id+400 子技能的父子技能ID，有些是有父技能才能随机出子技能，没有父就是0
        // 子key (uid + 1) * 10000 + 小技能id 表示当前玩家解锁该小技能数量
        hashtable rmSkHash = InitHashtable()
    endglobals

    // 获取技能图标
    function getSkillIcon takes integer bigSid, integer smallSid returns string
        return LoadStr(rmSkHash, bigSid, smallSid + 10)
    endfunction
    // 获取技能名称
    function getSkillName takes integer bigSid, integer smallSid returns string
        return LoadStr(rmSkHash, bigSid, smallSid + 10 + 100)
    endfunction
    // 获取技能描述
    function getSkillInstro takes integer bigSid, integer smallSid returns string
        return LoadStr(rmSkHash, bigSid, smallSid + 10 + 200)
    endfunction

    // 添加指定技能的小技能数据
    // skillId 技能Id，smSkId 指定的小技能Id，instro 技能介绍，maxCount 技能最大能随机到的次数，weight 父id
    function addSmallSkill takes integer skillId, integer smSkId, string ico, string name, string instro, integer maxCount, integer weight returns nothing
        call SaveStr(rmSkHash, skillId, smSkId + 10, ico)
        call SaveStr(rmSkHash, skillId, smSkId + 10 + 100, name)
        call SaveStr(rmSkHash, skillId, smSkId + 10 + 200, instro)
        call SaveInteger(rmSkHash, skillId, smSkId + 10 + 300, maxCount)
        call SaveInteger(rmSkHash, skillId, smSkId + 10 + 400, weight)
    endfunction

    // 获取小技能最大能随机到的次数
    function getSmallSkillMaxCount takes integer skillId, integer smSkId returns integer
        return LoadInteger(rmSkHash, skillId, smSkId + 10 + 300)
    endfunction

    // 获取小技能的父小技能Id
    function getSmalSkillParentId takes integer skillId, integer smSkId returns integer
        return LoadInteger(rmSkHash, skillId, smSkId + 10 + 400)
    endfunction

    // 增加小技能选择的次数
    function addSmallSkillStudyCount takes integer uid, integer skillId, integer smSkId returns nothing
        call SaveInteger(rmSkHash, skillId, (uid + 1) * 10000 + smSkId, LoadInteger(rmSkHash, skillId, (uid + 1) * 10000 + smSkId) + 1)
    endfunction
    // 获取小技能学习累加次数
    function getSmallSkillStudyCount takes integer uid, integer skillId, integer smSkId returns integer
        return LoadInteger(rmSkHash, skillId, (uid + 1) * 10000 + smSkId)
    endfunction


    // 设置大技能的小技能数量
    function setSmallSkillCount takes integer skillId, integer count returns nothing
        call SaveInteger(rmSkHash, skillId, 1, count)
    endfunction
    // 获取大技能的小技能数量
    function getSmallSkillCount takes integer skillId returns integer
        return LoadInteger(rmSkHash, skillId, 1)
    endfunction

    // 完全随机一个技能ID
    function randomBID takes integer uid returns integer
        return allSkillId[GetRandomInt(0, allSkillIdCount - 1)]
    endfunction
    // 随机一个大技能，排除掉随机随机出来的id
    function randomBIDByPaiChu takes integer uid, integer bigId1, integer bigId2 returns integer
        // 如果随机100次随机不到，就随便重复把
        local integer id = 0
        local integer loopi = 0
        loop
            exitwhen loopi > 100
            set id = randomBID(uid)
            if id != bigId1 and id != bigId2 then
                call DoNothing() YDNL exitwhen true//(  )
            endif
            set loopi = loopi + 1
        endloop

        return id
    endfunction

    // 获取玩家拥有的技能个数
    function getSkillCount takes integer uid returns integer
        local integer count = 0
        local integer loopi = 0
        loop
            exitwhen loopi >= 20
            if unlockedSkillId[uid * 20 + loopi] > 0 then
                set count = count + 1
            endif
            set loopi = loopi + 1
        endloop

        return count
    endfunction
    // 随机一个已经拥有的大技能ID
    function randomBIDHas takes integer uid returns integer
        return unlockedSkillId[uid * 20 + GetRandomInt(0, getSkillCount(uid) - 1)]
    endfunction
    // 获取玩家格子数量
    function getGridCount takes integer uid returns integer
        return unlockedSkillGrid[uid]
    endfunction

    // 随机小技能ID
    function getRandomSmIdByBigId takes integer uid, integer bigId returns integer
        local integer total = getSmallSkillCount(bigId)
        local integer id = 0
        local integer loopi = 0
        local integer parentId
        local integer parentId2

        loop
            // 如果随机了2000次还没随机到，就返回0，加攻击力
            exitwhen loopi > 2000
            set loopi = loopi + 1

            set id = GetRandomInt(1, total)

            // 判断是否有父ID，如果有，则判断是否已经学习过
            // 如果没有学习，则学习返回父小技能ID
            set parentId = getSmalSkillParentId(bigId, id)
            if parentId > 0 then
                // 有两层链接，判断第一层
                if getSmallSkillStudyCount(uid, bigId, parentId) < getSmallSkillMaxCount(bigId, parentId) then
                    // 判断第二层爷爷
                    set parentId2 = getSmalSkillParentId(bigId, parentId)
                    if parentId2 > 0 and getSmallSkillStudyCount(uid, bigId, parentId2) < getSmallSkillMaxCount(bigId, parentId2) then
                        return parentId2
                    else
                        return parentId
                    endif
                endif
            endif

            // 判断是否已经随机次数达到最大了
            if getSmallSkillStudyCount(uid, bigId, id) < getSmallSkillMaxCount(bigId, id) then
                return id
            endif
        endloop

        return id
    endfunction

    // TODO 随机小技能为0的时候要给攻击力或者其他奖励，因为提升到顶级了
    // 随机大技能id
    function randomSkillId takes integer uid returns nothing

        // [uid * 20 + id]
        // integer array unlockedSkillId
        
        // 玩家已经学习的技能个数
        local integer count = 1
        local integer id = 0
        local integer loopi
        local integer pc1 = 0
        local integer pc2 = 0

        // 随机第一个卡牌的大技能ID
        if GetRandomInt(1, 100) <= 70 then
            // 随机到已经有的技能
            set id = randomBIDHas(uid)
        else
            // 完全随机大技能ID
            // 完全随机要注意，如果已经已经拥有的个数达到上限，也就是没格子了，就必须随机旧技能
            if getSkillCount(uid) >= getGridCount(uid) then
                set id = randomBIDHas(uid)
            else
                set id = randomBID(uid)
            endif
        endif
        set cardSkillId[uid * 8 + 0] = id
        set cardSkillIdSmall[uid * 8 + 0] = getRandomSmIdByBigId(uid, id)

        // 随机第二个卡牌的大技能ID
        if GetRandomInt(1, 100) <= 60 then
            // 随机到已经有的技能
            set id = randomBIDHas(uid)
        else
            // 完全随机大技能ID
            // 完全随机要注意，如果已经已经拥有的个数达到上限，也就是没格子了，就必须随机旧技能
            if getSkillCount(uid) >= getGridCount(uid) then
                set id = randomBIDHas(uid)
            else
                // 完全随机需要判断上一个随机的大技能是否已经解锁，如果已经解锁，则需要排除，不能在本次选择中出来
                if cardSkillId[uid * 8 + 0] != 1 and cardSkillIdSmall[uid * 8 + 0] == 1 then
                    // 第一个飞剑术特殊，顶级父元素不是1，默认解锁，所以要排除掉第一个飞剑术
                    // 说明没解锁
                    set pc1 = cardSkillId[uid * 8 + 0]
                endif
                set id = randomBIDByPaiChu(uid, pc1, pc2)
            endif
        endif
        set cardSkillId[uid * 8 + 1] = id
        set cardSkillIdSmall[uid * 8 + 1] = getRandomSmIdByBigId(uid, id)

        // 随机第三个卡牌的大技能ID
        // 完全随机
        // 完全随机需要判断上一个随机的大技能是否已经解锁，如果已经解锁，则需要排除，不能在本次选择中出来
        if cardSkillId[uid * 8 + 1] != 1 and cardSkillIdSmall[uid * 8 + 1] == 1 then
            // 第一个飞剑术特殊，顶级父元素不是1，默认解锁，所以要排除掉第一个飞剑术
            // 说明没解锁
            set pc2 = cardSkillId[uid * 8 + 1]
        endif
        if getSkillCount(uid) >= getGridCount(uid) then
            set id = randomBIDHas(uid)
        else
            set id = randomBIDByPaiChu(uid, pc1, pc2)
        endif
        set cardSkillId[uid * 8 + 2] = id
        set cardSkillIdSmall[uid * 8 + 2] = getRandomSmIdByBigId(uid, id)

    endfunction

    private function init takes nothing returns nothing
        local integer loopi = 0
        local integer skillId
        local integer uid = 0
        // 初始化技能池
        loop
            exitwhen loopi >= allSkillIdCount
            set allSkillId[loopi] = loopi + 1
            set loopi = loopi + 1
        endloop
        // 初始化格子和初始学习技能
        loop
            exitwhen uid > PLAYER_NUMBER
            // 已经解锁的技能
            set unlockedSkillIdCount[uid] = 0
            // 默认解锁的技能格子
            set unlockedSkillGrid[uid] = 4
            // 默认学习1技能飞剑术
            call newSkillButton(uid, 1, "BTNicofjs.blp", 0, ct_flyCD[uid])
            set uid = uid + 1
        endloop

        // 初始化飞剑术随机数据
        set skillId = 1
        call addSmallSkill(skillId, 1, "BTNico.blp", "数量", "飞剑数量+1", 8, 0)
        call addSmallSkill(skillId, 2, "BTNico.blp", "伤害增幅", "飞剑伤害增幅+（20~80）%", 50, 0)
        call addSmallSkill(skillId, 3, "BTNico.blp", "爆破", "飞剑命中单位后攻击*0.5的爆炸范围伤害", 1, 0)
        call addSmallSkill(skillId, 4, "BTNico.blp", "爆破范围", "飞剑爆炸范围增幅+（20~60）%", 10, 3)
        call addSmallSkill(skillId, 5, "BTNico.blp", "爆破伤害", "飞剑命中爆炸伤害增幅+（20~60）%", 20, 3)
        call addSmallSkill(skillId, 6, "BTNico.blp", "贯穿", "飞剑穿透+1", 10, 0)
        call addSmallSkill(skillId, 7, "BTNico.blp", "火焰剑", "将飞剑变为火焰剑，每秒燃烧怪物攻击力*0.2伤害，持续5秒", 1, 0)
        call addSmallSkill(skillId, 8, "BTNico.blp", "火焰增幅", "火焰剑灼烧增幅+（20~80）%", 10, 7)
        call addSmallSkill(skillId, 9, "BTNico.blp", "射程", "飞剑射程+（300~1000）", 10, 0)
        call addSmallSkill(skillId, 10, "BTNico.blp", "连射", "飞剑连射次数+1", 10, 0)
        call setSmallSkillCount(skillId, 10)

        // 火焰弹
        set skillId = 2
        call addSmallSkill(skillId, 1, "BTNico.blp", "火焰弹", "每5秒释放一个火焰弹对目标造成攻击力*1.2的火焰伤害，并且爆炸造成攻击力*1的火焰伤害", 1, 0)
        call addSmallSkill(skillId, 2, "BTNico.blp", "增幅", "伤害+80%", 20, 1)
        call addSmallSkill(skillId, 3, "BTNico.blp", "连珠", "火焰弹额外释放一次", 5, 1)
        call addSmallSkill(skillId, 4, "BTNico.blp", "范围增幅", "火焰弹爆炸范围增幅+20%", 10, 1)
        call addSmallSkill(skillId, 5, "BTNico.blp", "伤害增幅", "火焰弹爆炸伤害增幅+40%", 20, 1)
        call setSmallSkillCount(skillId, 5)

        // 掌心雷
        set skillId = 3
        call addSmallSkill(skillId, 1, "BTNico.blp", "掌心雷", "随机对指定范围造成攻击力*2的闪电伤害", 1, 0)
        call addSmallSkill(skillId, 2, "BTNico.blp", "范围增幅", "爆炸范围增幅+20%", 10, 1)
        call addSmallSkill(skillId, 3, "BTNico.blp", "伤害增幅", "伤害增幅+40%", 20, 1)
        call addSmallSkill(skillId, 4, "BTNico.blp", "连续", "额外释放一次", 6, 1)
        call addSmallSkill(skillId, 5, "BTNico.blp", "高压", "20%的概率麻痹单位0.5秒", 6, 1)
        call addSmallSkill(skillId, 6, "BTNico.blp", "高压概率", "麻痹概率+10%", 9, 5)
        call addSmallSkill(skillId, 7, "BTNico.blp", "麻痹时间", "麻痹时间+0.5", 9, 5)
        call setSmallSkillCount(skillId, 7)

        // 闪电链
        set skillId = 4
        call addSmallSkill(skillId, 1, "BTNico.blp", "闪电链", "每6秒释放一次，连续对5个单位造成攻击力*0.5的闪电伤害", 1, 0)
        call addSmallSkill(skillId, 2, "BTNico.blp", "伤害增幅", "伤害增幅+30%", 20, 1)
        call addSmallSkill(skillId, 3, "BTNico.blp", "连续", "闪电命中单位额外+1", 10, 1)
        call addSmallSkill(skillId, 4, "BTNico.blp", "闪电余威", "闪电链击中后每0.5秒造成一次攻击力*0.2的闪电伤害，持续三次", 10, 1)
        call addSmallSkill(skillId, 5, "BTNico.blp", "余威增幅", "持续伤害增幅+30%", 10, 4)
        call addSmallSkill(skillId, 6, "BTNico.blp", "余威次数", "余威次数+1", 10, 4)
        call setSmallSkillCount(skillId, 6)

        // 寒冰箭
        set skillId = 5
        call addSmallSkill(skillId, 1, "BTNico.blp", "寒冰箭", "对目标造成攻击力*0.5的冰霜伤害", 1, 0)
        call addSmallSkill(skillId, 2, "BTNico.blp", "伤害增幅", "伤害增幅+30%", 20, 1)
        call addSmallSkill(skillId, 3, "BTNico.blp", "距离", "释放距离+300", 10, 1)
        call addSmallSkill(skillId, 4, "BTNico.blp", "冰霜连射", "连射数量+1", 3, 1)
        call addSmallSkill(skillId, 5, "BTNico.blp", "冰霜冻结", "寒冰箭命中单位后冻结0.5秒", 8, 1)
        call addSmallSkill(skillId, 6, "BTNico.blp", "冻结增幅", "冻结时间+0.5", 9, 5)
        call addSmallSkill(skillId, 7, "BTNico.blp", "冰霜减速", "寒冰箭命中减速20%", 1, 1)
        call addSmallSkill(skillId, 8, "BTNico.blp", "减速增幅", "命中减速增加额外5%", 10, 7)
        call addSmallSkill(skillId, 9, "BTNico.blp", "冻伤", "寒冰箭命中冻伤持续掉血攻击力*0.1的冰霜伤害", 10, 1)
        call addSmallSkill(skillId, 10, "BTNico.blp", "冻伤增幅", "冻伤伤害增幅+50%", 10, 9)
        call addSmallSkill(skillId, 11, "BTNico.blp", "冻伤次数", "冻伤次数+2", 10, 9)
        call addSmallSkill(skillId, 12, "BTNico.blp", "贯穿", "寒冰箭穿透+1", 5, 1)
        call addSmallSkill(skillId, 13, "BTNico.blp", "分裂", "寒冰箭命中单位后分裂成三个小寒冰箭碰到目标造成攻击力*0.1的冰霜伤害", 1, 1)
        call addSmallSkill(skillId, 14, "BTNico.blp", "分裂数量", "分裂数量+1", 2, 13)
        call addSmallSkill(skillId, 15, "BTNico.blp", "小寒冰箭增幅", "小寒冰箭伤害增幅+50%", 20, 13)
        call addSmallSkill(skillId, 16, "BTNico.blp", "小寒冰箭冻结", "小寒冰箭命中单位冻结0.5秒", 1, 13)
        call addSmallSkill(skillId, 17, "BTNico.blp", "小寒冰箭冻结增幅", "小寒冰箭冻结时间+0.5", 9, 16)
        call addSmallSkill(skillId, 18, "BTNico.blp", "小寒冰箭减速", "小寒冰箭命中减速10%", 1, 13)
        call addSmallSkill(skillId, 19, "BTNico.blp", "小寒冰箭减速增幅", "小寒冰箭减速增加额外5%", 10, 18)
        call addSmallSkill(skillId, 20, "BTNico.blp", "小寒冰冻伤", "小寒冰箭命中单位冻伤持续伤害", 1, 13)
        call setSmallSkillCount(skillId, 20)
    endfunction
endlibrary
